<!DOCTYPE html>

<html lang="en">
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width">
	<title>DocStrap Index</title>

	<!--[if lt IE 9]>
	<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
	<![endif]-->
	<link type="text/css" rel="stylesheet" href="styles/sunlight.default.css">

	<link type="text/css" rel="stylesheet" href="styles/site.flatly.css">

</head>

<body>

<div class="navbar navbar-default navbar-fixed-top navbar-inverse">
<div class="container">
	<div class="navbar-header">
		<a class="navbar-brand" href="index.html">DocStrap</a>
		<button class="navbar-toggle" type="button" data-toggle="collapse" data-target="#topNavigation">
			<span class="icon-bar"></span>
			<span class="icon-bar"></span>
			<span class="icon-bar"></span>
        </button>
	</div>
	<div class="navbar-collapse collapse" id="topNavigation">
		<ul class="nav navbar-nav">
			
			<li class="dropdown">
				<a href="classes.list.html" class="dropdown-toggle" data-toggle="dropdown">Classes<b class="caret"></b></a>
				<ul class="dropdown-menu ">
					<li><a href="Handle.html">Handle</a></li><li><a href="Include.html">Include</a></li>
				</ul>
			</li>
			
		</ul>
        
            <div class="col-sm-3 col-md-3">
                <form class="navbar-form" role="search">
                    <div class="input-group">
                        <input type="text" class="form-control" placeholder="Search" name="q" id="search-input">
                        <div class="input-group-btn">
                            <button class="btn btn-default" id="search-submit"><i class="glyphicon glyphicon-search"></i></button>
                        </div>
                    </div>
                </form>
            </div>
        
	</div>

</div>
</div>


<div class="container" id="toc-content">
<div class="row">

	
	<div class="col-md-8">
	
		<div id="main">
			

	
	











	
	





    <section class="readme-section">
        <article><h1>Handle.js</h1><p>Handle.js，一个基于 koa 和 sequelize 的中间库，让你只专注于接口逻辑。</p>
<p><a href="https://yeshimei.github.io/Handle.js/">api 文档</a>。</p>
<h1>Usage</h1><pre class="prettyprint source lang-javascript"><code>// 导入 sequelize 模型
import { article } from '../models/db'

// 把 article 传入 Handle，并实例化
const article = new Handle(article)

// 生成一个查询当前模型所有数据的 koa 中间件
const find = article.findAll()

// 绑定到路由
router.get('/article/find', find)</code></pre><h1>开始</h1><h2>实例的模型方法一览</h2><p>Handle.js 代理了部分 sequelize 模型方法，以下：</p>
<ul>
<li>GET 请求<ul>
<li>findOne</li>
<li>findAll</li>
<li>findById</li>
<li>findOrCreate</li>
<li>findAndCountAll</li>
<li>findAndCount</li>
<li>findCreateFind</li>
<li>count</li>
<li>max</li>
<li>min</li>
<li>sun</li>
</ul>
</li>
<li>POST 请求<ul>
<li>create</li>
<li>bulkCreate</li>
<li>update</li>
<li>destroy</li>
<li>increment</li>
<li>decrement</li>
</ul>
</li>
</ul>
<p>同时，Handle.js 还内置以下模型方法：</p>
<ul>
<li>POST 请求<ul>
<li>toggle</li>
</ul>
</li>
</ul>
<p>以上所有模型方法统称为快捷方法，调用后生成一个 async 的 koa 中间件函数，可以直接挂载路由。此外，还提供了一套对应的过程方法，调用后仅返回原生数据，可供进一步处理。以下：</p>
<ul>
<li>GET 请求<ul>
<li>rawFindOne</li>
<li>rawFindAll</li>
<li>rawFindById</li>
<li>rawFindOrCreate</li>
<li>rawFindAndCountAll</li>
<li>rawFindAndCount</li>
<li>rawFindCreateFind</li>
<li>rawCount</li>
<li>rawMax</li>
<li>rawMin</li>
<li>rawSun</li>
</ul>
</li>
<li>POST 请求<ul>
<li>rawCreate</li>
<li>rawBulkCreate</li>
<li>rawUpdate</li>
<li>rawDestroy</li>
<li>rawIncrement</li>
<li>rawDecrement</li>
<li>rawToggle</li>
</ul>
</li>
</ul>
<h2>where 子句简写</h2><ol>
<li>字符串语法</li>
</ol>
<pre class="prettyprint source lang-javascript"><code>
article.findOne('id')
// 内部将替换成
// { 
//   where: { id:  d.id } 
// }
//
</code></pre><p>GET 请求下，<code>d</code> 为 <code>ctx.query</code> 对象。POST 请求下，<code>d</code> 为 <code>ctx.request.body</code> 对象（默认为 x-www-form-urlencoded 类型）。</p>
<ol start="2">
<li>多条件</li>
</ol>
<pre class="prettyprint source lang-javascript"><code>
article.findOne(['id', 'uid'])
// 内部将替换成
// { 
//   where: { 
//     id:  d.id,
//     uid: d.uid  
//  } 
// }
//</code></pre><ol start="3">
<li>提供默认值</li>
</ol>
<pre class="prettyprint source lang-javascript"><code>article.findOne(['id', ['uid': 1]])
// 内部将替换成
// { 
//   where: { 
//     id:  d.id,
//     uid: 1  
//  } 
// }
//</code></pre><ol start="4">
<li>别名</li>
</ol>
<pre class="prettyprint source lang-javascript"><code>article.findOne([['id', '@aid'], ['uid', 1]])
// 内部将替换成
// { 
//   where: { 
//     id:  d.aid,
//     uid: 1
//  } 
// }
//</code></pre><h2>更强大的函数式</h2><p>函数式下支持所有 sequelize 模型选项中合法的选项。（具体请参考 <a href="http://docs.sequelizejs.com/class/lib/model.js~Model.html">Model</a>）</p>
<pre class="prettyprint source lang-javascript"><code>article.findOne(d => ({
  where: {
    id: d.aid,
    uid: 1
  },
}))</code></pre><p>更复杂的分页查询。</p>
<pre class="prettyprint source lang-javascript"><code>article.findAll(d => {
  const count = d.count || 5
  const page = d.page || 0
  return {

    where: {
      uid: d.uid
    },

    limit: count,
    offset: page * count
  }
}),</code></pre><h2>原生数据</h2><p><code>create()</code> 将自动把 <code>d</code> 作为数据增加到数据库中。</p>
<pre class="prettyprint source lang-javascript"><code>article.create()</code></pre><p>但是，对于 <code>increment()</code> 你可能只想增加某个字段的值，你可以直接指定原生数据。</p>
<pre class="prettyprint source lang-javascript"><code>article.increment('comment_count', 'id')</code></pre><p>注意，原生数据在内部不会做任何处理。</p>
<h2>选项对象</h2><p>请参考 <a href="https://yeshimei.github.io/Handle.js/Handle.html">API 手册</a></p>
<h1>过程</h1><p><code>process</code> 将一系列操作封装到一起，提供了可以验证、过滤、重组等处理数据的能力，并且非常适合非事务性的多次数据库操作等场景。通常，需要配合过程方法使用。</p>
<pre class="prettyprint source lang-javascript"><code>// 查询用户收藏的文章
articleStar.process(async function (d) {

  const {count = 5, page = 0, uid} = d

  const res = await this.rawFindAll({

    include: [
      {
        // 关联查询文章数据
        model: Article,
        // 并且查询文章的用户数据
        include: [User]
      }
    ],
    // 通过 uid 查询
    where: { uid },
    // 分页
    limit: count,
    offset: page * count
  })
  // 过滤数据，仅返回文章数据
  return res && res.map(d => d.article)
})</code></pre><p>另外，当出现一些重复逻辑时，你也可以很方便的提取出来复用。</p>
<h1>作用域</h1><p><code>scope</code> 是复用模型选项对象的最佳选择，它在内部使用了 <code>merge</code> 深度混合所有 <code>scope</code> 到选项对象中。外在而言，让你的代码更直观、简洁、易懂和良好的复用性，更易于重构和修改。</p>
<p>把上面的分页逻辑封装成为一个 提供参数的 scope。</p>
<pre class="prettyprint source lang-javascript"><code>function pagination (defaultCount = 5, defaultPage = 0) => {
  return d => {
    const count = d.count || defaultCount
    const page = d.page || defaultPage
    return {
      limit: count,
      offset: page * count
    }
  }
}</code></pre><p>然后，通过 <code>scope()</code> 方法到处复用。</p>
<pre class="prettyprint source lang-javascript"><code>// 查询所有指定 uid 的数据，且每页返回 10 条数据
article.scope(pagination(10)).findAll('uid')
// 使用 pagination 函数提供默认值
article.scope(pagination()).findAll('uid')
// 其实，你可以省略掉 pagination 前面的 ()
article.scope(pagination).findAll('uid')

// 同时，scope 还可以是对象
articleStar.process(async function (d) {
  const include = {
    include: [
      {
        model: Article,
        include: [User]
      }
    ],
  }

  const res = await this
    .scope(pagination, include)
    .rawFindAll('uid')

  return res && res.map(d => d.article)
}),</code></pre><p><code>scope()</code> 方法合并的选项对象<strong>仅在第一次被使用的方法上有效</strong>。如果，想要让所有当前实例的模型方法都共享某些 scope ，可以通过 <code>defaultScope()</code> 添加。注意，每个 <code>scope</code> 都必须最终返回一个选项对象。</p>
<h1>关联查询</h1><p><code>Include</code> 是 Handle.js 一个静态工具类，用于统一管理整个应用的关联数据。</p>
<pre class="prettyprint source lang-javascript"><code>const { Include } = Handle

Include
  // 添加名为 article 的关联，并忽略查询一些属性。
  .add('article', {
    model: Article,
    attributes: {
      exclude: ['content', 'createdAt', 'updateAt']
    },
  })
  // 同时添加一个名为 user 的关联。
  .add('user', {
    model: User,
    attributes: {
      exclude: ['password', 'lock', 'freeze', 'power' ,'createdAt', 'updateAt']
    },
  })</code></pre><p>然后，通过 <code>Handle.create()</code> 方法，可以简单的组合已添加关联的层级关系。</p>
<pre class="prettyprint source lang-javascript"><code>articleStar.process(async function (d) {
    const res = await this
      .scope(pagination, Include.create({
        article: ['user']
      }))
      .rawFindAll('uid')
    return res && res.map(d => d.article)
  }),</code></pre><p><code>Handle</code> 在可高度复用关联数据的同时，又能以最小化、最简单的方式组织和管理。</p>
<h1>事务</h1><p><code>transaction</code> 是通过 <code>process</code> 简单的对 sequelize 原生事务的封装。在使用上，和 <code>process</code> 完全一致。</p>
<pre class="prettyprint source"><code>articleStar.transaction(async function (d) {
  /** 事务相关的处理 */
  return /** 返回处理后的数据 */
}),</code></pre><h1>钩子</h1><p>（暂无）</p>
<h1>Mock 支持</h1><p>Handle.js 提供了 mock 的接口，但它依赖于 mock 库。这里，我推荐使用 <a href="https://github.com/nuysoft/Mock">mockjs</a>。</p>
<p>首先，你需要通过选项对象传入 mock 库以开启 <code>mock()</code> 方法</p>
<pre class="prettyprint source lang-javascript"><code>import Mock from 'mockjs'

// 指定要使用 mockjs
const article = new Handle(Article)
article.options.mock = Mock</code></pre><p>然后，使用实例的 <code>mock()</code> 方法。</p>
<pre class="prettyprint source lang-javascript"><code>// 批量向 article 表中插入 20 条数据
article.mock({
 'data|20': [
   {
     title: '@ctitle',
     content: '@cparagraph'
   }
 ]
})</code></pre><p><code>mock()</code> 内部调用实例的 <code>bulkCreate()</code> 方法批量添加数据（注意，因为使用了原生数据入口，所以不会对数据做任何处理）</p>
<h1>一些差异性的问题</h1><p>（敬请期待）</p>
<h1>插件系统</h1><p>（暂无）</p></article>
    </section>







		</div>
	</div>

	<div class="clearfix"></div>

	
		<div class="col-md-3">
			<div id="toc" class="col-md-3 hidden-xs hidden-sm hidden-md"></div>
		</div>
	

</div>
</div>


    <div class="modal fade" id="searchResults">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
            <h4 class="modal-title">Search results</h4>
          </div>
          <div class="modal-body"></div>
          <div class="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
          </div>
        </div><!-- /.modal-content -->
      </div><!-- /.modal-dialog -->
    </div>


<footer>


<span class="jsdoc-message">
	Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
	
		on 2018-08-11T10:32:04+08:00
	
	using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
</span>
</footer>

<script src="scripts/docstrap.lib.js"></script>
<script src="scripts/toc.js"></script>

    <script type="text/javascript" src="scripts/fulltext-search-ui.js"></script>


<script>
$( function () {
	$( "[id*='$']" ).each( function () {
		var $this = $( this );

		$this.attr( "id", $this.attr( "id" ).replace( "$", "__" ) );
	} );

	$( ".tutorial-section pre, .readme-section pre, pre.prettyprint.source" ).each( function () {
		var $this = $( this );

		var example = $this.find( "code" );
		exampleText = example.html();
		var lang = /{@lang (.*?)}/.exec( exampleText );
		if ( lang && lang[1] ) {
			exampleText = exampleText.replace( lang[0], "" );
			example.html( exampleText );
			lang = lang[1];
		} else {
			var langClassMatch = example.parent()[0].className.match(/lang\-(\S+)/);
			lang = langClassMatch ? langClassMatch[1] : "javascript";
		}

		if ( lang ) {

			$this
			.addClass( "sunlight-highlight-" + lang )
			.addClass( "linenums" )
			.html( example.html() );

		}
	} );

	Sunlight.highlightAll( {
		lineNumbers : true,
		showMenu : true,
		enableDoclinks : true
	} );

	$.catchAnchorLinks( {
        navbarOffset: 10
	} );
	$( "#toc" ).toc( {
		anchorName  : function ( i, heading, prefix ) {
			return $( heading ).attr( "id" ) || ( prefix + i );
		},
		selectors   : "#toc-content h1,#toc-content h2,#toc-content h3,#toc-content h4",
		showAndHide : false,
		smoothScrolling: true
	} );

	$( "#main span[id^='toc']" ).addClass( "toc-shim" );
	$( '.dropdown-toggle' ).dropdown();

    $( "table" ).each( function () {
      var $this = $( this );
      $this.addClass('table');
    } );

} );
</script>



<!--Navigation and Symbol Display-->


<!--Google Analytics-->



    <script type="text/javascript">
        $(document).ready(function() {
            SearcherDisplay.init();
        });
    </script>


</body>
</html>